﻿using System;
using System.Threading;

namespace RockBus.Threading
{
    public class TimeoutHelper<TState>
    {
        public TimeoutHelper(Action<TState, bool> callback, TState state, int timeoutMs)
        {
            this.State = state;
            this.TimeoutMs = timeoutMs;
            this.Callback = callback;
            this.Timer = new Timer(this.TimerCallback, true, timeoutMs, Timeout.Infinite);
        }

        public void Complete()
        {
            this.TimerCallback(false);
        }

        public TState State { get; private set; }

        public int TimeoutMs { get; private set; }

        private Action<TState, bool> Callback { get; set; }

        private Timer Timer { get; set; }

        public bool IsTimedOut { get; set; }

        private int Guard;

        private void TimerCallback(object isTimedOut)
        {
            if (Interlocked.CompareExchange(ref this.Guard, 1, 0) == 1)
            {
                return;
            }

            this.IsTimedOut = (bool)isTimedOut;
            this.Timer.Dispose();
            this.Callback(this.State, this.IsTimedOut);
        }
    }
}